﻿using AppDataStruct;
using ComClassLibrary;
using ComLib.ComFun;
using ComLib.ComType;
using KWindow.KPageCore;
using LogLib;
using Newtonsoft.Json.Linq;
using System;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace YSLPages
{
    public partial class PageLivePhoto : PageControlBase
    {

        #region Custom Controls
        private Button btnTakePhoto;
        private PictureBox pbxCapturedPhoto;
        private PictureBox pbxLiveView;
        #endregion

        private AppDirectory appDirs = new AppDirectory();
        private ShareMemory shareMem = new ShareMemory(false);

        private bool _bExit = false;
        private byte[] _dataLiveView = new byte[ShareMemory.dataLength];
        private static object _lockflag = new object();
        private const string PhotoCapturer = "PhotoCapturer";
        private const int MaxCount = 4;
        private PreApplyInfo _appInfo = null;
        private DeviceControl _device = null;
        private bool HZChecked = false;
        private bool _takeByManual = false;
        private void InitDeviceControl()
        {
            _device = new DeviceControl("PhotoCapturer");
            _device.OnCatchException = OnCatchException;
            _device.OnDone = OnPhotoTakenSuccess;
            _device.OnDoFailed = OnPhotoTakenFailed;
            _device.OnTimeout = OnPhotoTakenTimeout;
            _device.Init();
        }

        private void OnPhotoTakenSuccess(string outParams)
        {
            string msg = string.Format("拍照成功, 返回: \n{0}", outParams);
            Log.WriteAsync(msg);
            Action handler = () =>
            {

                btnTakePhoto.Enabled = true;
                OnPhotoTaken(outParams);
            };
            this.Invoke(handler);
        }

        private void OnPhotoTakenFailed(string outParams, string error)
        {
            string msg = string.Format("资料翻拍失败: \n outParams: {0}, \n error: {1}", outParams, error);
            Log.WriteAsync(msg);
            Action handler = () =>
            {
                MessageBox.Show("资料翻拍失败!");
            };
            this.Invoke(handler);
        }

        private void OnPhotoTakenTimeout(string outParams)
        {
            string msg = string.Format("资料翻拍超时: \n{0}", outParams);
            Log.WriteAsync(msg);
            Action handler = () =>
            {
                MessageBox.Show("资料翻拍超时.");
            };
            this.Invoke(handler);
        }

        private void OnCatchException(string outParams)
        {
            string msg = string.Format("设备运行发生了异常: \n{0}", outParams);
            Log.WriteAsync(msg);
            Action<string> handler = (e) =>
            {
                MessageBox.Show(e);
                StopWork();
                ClearData();
                Process.ToHome();
            };
            this.Invoke(handler, msg);
        }

        /// <summary>
        /// 办理业务个人的材料翻拍照片保存路径
        /// </summary>
        private string _personalDirectory = "";
        private string PersonalDirectory
        {
            get
            {
                if (string.IsNullOrEmpty(_personalDirectory) && _appInfo != null)
                {
                    string passportID = _appInfo.SFZH + "_" + DateTime.Now.ToString("yyyyMMddHHmmss");
                    _personalDirectory = Path.Combine(appDirs.Materials, passportID);
                }

                if (string.IsNullOrEmpty(_personalDirectory))
                {
                    _personalDirectory = Path.Combine(appDirs.Materials, DateTime.Now.ToString("yyyyMMddHHmmss"));
                }

                if (!Directory.Exists(_personalDirectory))
                {
                    Directory.CreateDirectory(_personalDirectory);
                }
                return _personalDirectory;
            }
        }

        public PageLivePhoto()
        {
            InitializeComponent();
            SetProcessBase(ProcessLivePhoto.Instance);
        }

        /// <summary>
        /// 应用语言
        /// </summary>
        /// <param name="code"></param>
        public override void ApplyLanguage(string code)
        {
            base.ApplyLanguage(code);
        }

        private void GetControls()
        {
            btnTakePhoto = GetControl<Button>("btnTakePhoto") as Button;
            pbxLiveView = GetControl<PictureBox>("pbxLiveView") as PictureBox;
            pbxCapturedPhoto = GetControl<PictureBox>("pbxCapturedPhoto") as PictureBox;

        }

        public override void InitCtrls()
        {
            base.InitCtrls();
            GetControls();
            //pbxLiveView.SizeMode = PictureBoxSizeMode.Zoom;
            //pbxCapturedPhoto.SizeMode = PictureBoxSizeMode.Zoom;
            pbxCapturedPhoto.BackgroundImageLayout = ImageLayout.Zoom;

            SetButtonDefaultStyles(btnTakePhoto);
            SetButtonDefaultStyles(buttonCancel);
            SetButtonDefaultStyles(buttonBack);
            SetButtonDefaultStyles(buttonNext);
        }

        private void PageCopyingPhotography_Load(object sender, EventArgs e)
        {
            Log.WriteAsync("====================[" + this.Name + "Start]====================");
        }

        //初始化窗体数据
        public override void InitData()
        {
            base.InitData();
            try
            {
                _appInfo = Process.GetValue<PreApplyInfo>("PreApplyInfo");

                if (Process.ContainsKey("HZChecked"))
                {
                    HZChecked = Process.GetValue<bool>("HZChecked");
                }
                else
                {
                    HZChecked = false;
                }

                btnTakePhoto.Enabled = true;

                if (IsMainPage && !string.IsNullOrEmpty(UIConfig.FormConfig.Tag))
                {
                    new Thread(() =>
                    {
                        int time = 3;
                        if (int.TryParse(UIConfig.FormConfig.Tag, out time))
                        {
                            //3秒拍照
                            Thread.Sleep(time * 1000);
                        }
                        else
                        {
                            Thread.Sleep(3000);
                        }
                        if (!_takeByManual)
                        {
                            btnTakePhoto_Click(null, null);
                        }
                    }).Start();
                }
                _personalDirectory = "";
                PictureBoxUpdate(null);
                UpdatePicture("");
            }
            catch (Exception ex)
            {
                Log.WriteAsync(ex.Message);
                Log.WriteException(ex.ToString());
            }
        }

        public override void StartWork()
        {
            base.StartWork();
            InitDeviceControl();
            StartCapturer();
            Speak("请摘下口罩，并目视前方摄像头，点击拍照按钮，完成现场人像采集后，点击下一步按钮");
        }

        public override void StopWork()
        {
            base.StopWork();
            //_motion.TurnOffLight(LEDS.PaperPrinter);
            StopCapturer();
        }

        private void StartCapturer()
        {
            _bExit = false;
            _device.Start();
            Thread.Sleep(100);
            Thread thread = new Thread(GetFrame);
            thread.Start();
        }

        private void StopCapturer()
        {
            _bExit = true;
            _device.Stop();
            PictureBoxUpdate(null);
        }

        private void PictureBoxUpdate(Bitmap img)
        {
            pbxLiveView.Invoke(new Action(() =>
            {
                if (pbxLiveView.Image != null)
                {
                    pbxLiveView.Image.Dispose();
                    pbxLiveView.Image = null;
                }

                pbxLiveView.Image = img;
                btnTakePhoto.Invalidate();
            }));
        }
        private void UpdatePicture(string path)
        {
            pbxCapturedPhoto.Invoke(new Action(() =>
            {
                if (File.Exists(path))
                {
                    if (pbxCapturedPhoto.BackgroundImage != null)
                    {
                        pbxCapturedPhoto.BackgroundImage.Dispose();
                        pbxCapturedPhoto.BackgroundImage = null;
                    }

                    System.IO.FileStream fs = new System.IO.FileStream(path, FileMode.Open, FileAccess.Read);
                    pbxCapturedPhoto.BackgroundImage = System.Drawing.Image.FromStream(fs);
                    fs.Close();
                }
                else
                {
                    pbxCapturedPhoto.BackgroundImage = null;
                }
            })
            );
        }
        /// <summary>
        /// 首次拍照时
        /// </summary>
        private void OnPhotoTaken(string param)
        {
            Speak("快门");
            JObject data = JObject.Parse(param);
            // int n = int.Parse((string)data["PhotoIndex"]);
            string filePath = (string)data["PhotoPath"];
            UpdatePicture(filePath);
            if (null != _appInfo)
                _appInfo.XCRX = filePath;
            //btnTakePhoto.Enabled = false;
            //OnConfirming();                
        }

        private void GetFrame()
        {
            Log.WriteAsync("开始GetFrame线程");
            //_dataLiveView = new byte[ShareMemory.dataLength];
            while (!_bExit)
            {
                try
                {
                    _dataLiveView = shareMem.GetShareMemData();
                    Bitmap bitmap = ComLib.ComFun.Tools.Byte2Bitmap(_dataLiveView);
                    PictureBoxUpdate(bitmap);
                    Thread.Sleep(50);
                    Application.DoEvents();
                }
                catch (System.Exception ex)
                {
                    //LogDB.Exception.Add(ex);
                    Thread.Sleep(300);
                }
            }
            PictureBoxUpdate(null);
            Log.WriteAsync("结束GetFrame线程");
        }

        /// <summary>
        /// 清理窗体数据(窗体本次做完后)
        /// </summary>
        public override void ClearData()
        {
            StopWork();
            _appInfo = null;
        }

        private void btnTakePhoto_Click(object sender, EventArgs e)
        {
            try
            {
                JObject inParam = new JObject();

                _takeByManual = true;
                inParam["PhotoDirectory"] = PersonalDirectory;
                inParam["PhotoIndex"] = _appInfo?.SFZH;
                string data = inParam.ToString();
                _device.Do(data);
                Log.WriteAsync("用户点击了拍照");
                btnTakePhoto.Enabled = false;
            }
            catch (Exception ex)
            {
                Log.WriteAsync(ex.Message);
                Log.WriteException(ex.ToString());
                //LogDB.Exception.Add(ex);
            }
        }

        private void OnConfirming()
        {
            //LogDB.Action.Add("现在开始确认拍摄照片...");

        }



        public override void UpdateData()
        {

            Process.SetValue("PreApplyInfo", _appInfo);
            //Process.SetValue("Materials", builder.ToString());
            //Process.SetValue("HighVideoPhotosPath", builder.ToString());

        }

        protected override void btnNext_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(_appInfo.XCRX) || !File.Exists(_appInfo.XCRX))
            {
                MessageBox.Show("请先进行拍照");
                return;
            }

            UpdateData();
            //StopCountdown();
            StopCapturer();
            //OnConfirming();

            if (_config.WorkFlow.HightCapture)
            {
                Process.ToNext();
            }
            else
            {
                int age = IDCardCheck.GetAge(_appInfo.CSRQ);
                if (age < 0)
                {
                    Log.WriteAsync($"计算年龄失败：{_appInfo.CSRQ}");
                }
                if (HZChecked && _config.WorkFlow.Signature && (age < 0 || age >= 7))  //7岁后才需要签名
                {
                    Process.ToAny("YSLPages.PageSignature");
                }
                else if (_config.WorkFlow.CapFinger)
                {
                    Process.ToAny("YSLPages.PageCaptureFinger");
                }
                else if (_config.WorkFlow.ReceiveWay)
                {
                    Process.ToAny("YSLPages.PageSelectReceiveWay");
                }
                else
                {
                    Process.ToAny("YSLPages.PagePreviewChecking");
                }
            }


            //base.btnNext_Click(sender, e);
        }

        protected override void btnCancel_Click(object sender, EventArgs e)
        {
            StopCapturer();
            base.btnCancel_Click(sender, e);
        }

    }
}
